﻿using System.Collections.Generic;
using System.IO;

namespace Engine.FileFormats3D
{
    public class WavefrontMaterialFile
    {
        #region Private Fields

        private List<WavefrontMaterial> materials;

        #endregion Private Fields

        #region Public Constructors

        public WavefrontMaterialFile()
        {
            this.materials = new List<WavefrontMaterial>();
        }

        #endregion Public Constructors

        #region Public Methods

        public static WavefrontMaterialFile FromFile(string fileName)
        {
            if (!File.Exists(fileName))
                return null;

            WavefrontMaterialFile materialFile = new WavefrontMaterialFile();
            FileStream fs = new FileStream(fileName, FileMode.Open);
            StreamReader sr = new StreamReader(fs);
            do
            {
                string line = sr.ReadLine();
                line = line.Replace('\t', ' ').Trim();

                string[] splittedLine = line.Split(' ');
                int offset = 0;
                if (splittedLine[0] == "\t")
                    offset++;

                switch (splittedLine[offset])
                {
                    case "newmtl":
                    case "\tnewmtl":
                        materialFile.materials.Add(new WavefrontMaterial(splittedLine[1]));
                        break;

                    case "map_Ka": //
                    case "\tmap_Ka": //

                        if (materialFile.materials.Count > 0)
                        {
                            string filepath = GetFilePath(splittedLine);
                            WavefrontMaterial material = materialFile.materials[materialFile.materials.Count - 1];
                            material.AlphaTextureName = Path.GetFileNameWithoutExtension(filepath);
                            materialFile.materials[materialFile.materials.Count - 1] = material;
                        }
                        break;

                    case "map_Kd": //
                    case "\tmap_Kd": //

                        if (materialFile.materials.Count > 0)
                        {
                            string filepath = GetFilePath(splittedLine);
                            WavefrontMaterial material = materialFile.materials[materialFile.materials.Count - 1];
                            material.DiffuseTextureName = Path.GetFileNameWithoutExtension(filepath);
                            materialFile.materials[materialFile.materials.Count - 1] = material;
                        }
                        break;
                }
            } while (!sr.EndOfStream);

            sr.Close();
            fs.Close();

            return materialFile;
        }

        public string GetDiffuseTextureName(string materialName)
        {
            for (int i = 0; i < this.materials.Count; i++)
            {
                if (this.materials[i].MaterialName.ToUpper() == materialName.ToUpper())
                {
                    return this.materials[i].DiffuseTextureName;
                }
            }

            return "none";
        }

        #endregion Public Methods

        #region Internal Methods

        /// <summary>
        /// When a material is found with the given name, the diffuse texture name
        /// will be returned.
        /// Otherwise the given materialname will be returned.
        /// </summary>
        /// <param name="The name of the material which should return the diffuse texturename."></param>
        /// <returns></returns>
        internal string GetTextureNameFromMaterial(string materialName)
        {
            for (int i = 0; i < this.materials.Count; i++)
            {
                if (materials[i].MaterialName == materialName)
                    return materials[i].DiffuseTextureName;
            }
            return materialName;
        }

        #endregion Internal Methods

        #region Private Methods

        private static string GetFilePath(string[] splittedLine)
        {
            string filepath = string.Empty;
            int offset = 0;
            if (splittedLine[0] == "\t")
                offset++;
            for (int i = 1; i < splittedLine.Length; i++)
            {
                filepath += splittedLine[offset + i] + " ";
            }

            return filepath;
        }

        #endregion Private Methods
    }
}